class Vue {
  constructor(options) {
    this.$options = options || {};
    this.$data = options.data || {};
    // el 传入是字符串获取dom对象，不是则返回原本的el
    this.$el = typeof options.el === 'string' ? document.querySelector(options.el) : options.el;
    new Observer(this.$data);
    this._proxyData(this.$data);
    // compiler的作用是处理dom对象,需要传递Vue实例,this指向Vue实例
    new Compiler(this)
  }

  /**
   * 
   * @param {*} data 
   * 将data注入到Vue实例中，转化成getter/setter，方便this访问
   */
  _proxyData(data) {
    Object.keys(data).forEach(key => {
      /**
       * Object.defineProperty(obj, prop, descriptor)
       * obj 要定义属性的对象
       * prop 要定义或修改的名称
       * descriptor 要定义或修改的属性描述符
       */
      // this 指向Vue实例
      Object.defineProperty(this, key, {
        // 可枚举的
        enumerable: true,
        // 描述符可修改或被删除
        configurable: true,

        // 访问属性时执行
        get() {
          return data[key];
        },

        // 修改属性时执行
        set(newVal) {
          if (newVal === data[key]) {
            return;
          }
          data[key] = newVal;
        }
      })
    })
  }
}